home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Xconq 7.1.0 / src / xconq-7.1.0 / kernel / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-07  |  15.8 KB  |  768 lines  |  [TEXT/R*ch]

  1. /* Random utilities not classifiable elsewhere.
  2.    Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996
  3.    Stanley T. Shebs.
  4.  
  5. Xconq is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.  See the file COPYING.  */
  9.  
  10. #include "config.h"
  11. #include "misc.h"
  12. extern void update_debugging PARAMS ((void));
  13. extern void toggle_debugging PARAMS ((int *flagp));
  14. extern void prealloc_debug PARAMS ((void));
  15. #include "lisp.h"
  16. #include "dir.h"
  17.  
  18. /* Accommodate certain obsolete (pre-ANSI) Unix systems. (?) */
  19.  
  20. #ifdef TIME_RETURNS_LONG
  21. #ifndef time_t
  22. #define time_t long
  23. #endif
  24. #endif
  25.  
  26. /* Direction-to-delta conversions. */
  27.  
  28. int dirx[NUMDIRS] = DIRX;
  29.  
  30. int diry[NUMDIRS] = DIRY;
  31.  
  32. /* If true, warnings will not be issued. */
  33.  
  34. int warnings_suppressed;
  35.  
  36. /* If true, allocation attempts will garner complaints, but not actually
  37.    fail.  (This is primarily for debugging addon code, such as new AIs
  38.    and user interfaces.) */
  39.  
  40. int xmalloc_warnings;
  41.  
  42. /* If true, all allocation will fail, suppresses further attempts. */
  43.  
  44. int memory_exhausted;
  45.  
  46. static char *padbuf;
  47.  
  48. /* Random number handling is important to game but terrible/nonexistent
  49.    in some systems.  Do it ourselves and hope it's better.  Unfortunately,
  50.    it's hard to prevent clueless hackers from calling rand or random
  51.    and thereby confusing everything, so there (should be) is a check in
  52.    the test dir that searches for calls to these. */
  53.  
  54. /* The random state *must* be at least 32 bits. */
  55.  
  56. long initrandstate = -1;
  57.  
  58. long randstate = -1;
  59.  
  60. /* Seed can come from elsewhere, for repeatability.  Otherwise, it comes
  61.    from the current time, scaled down to where 32-bit arithmetic won't
  62.    overflow. */
  63.  
  64. void
  65. init_xrandom(seed)
  66. int seed;
  67. {
  68.     time_t tm;
  69.         
  70.     if (seed >= 0) {
  71.     /* If the random state is already set, changes are somewhat
  72.        suspicious. */
  73.     if (randstate >= 0) {
  74.         Dprintf("Randstate being changed from %d to %d\n",
  75.             randstate, seed);
  76.     }
  77.     randstate = seed;
  78.     } else {
  79.         time(&tm);
  80.         randstate = (long) tm;
  81.     }
  82.     /* Whatever its source, put the randstate into known range (0 - 99999). */
  83.     randstate = ABS(randstate);
  84.     randstate %= 100000L;
  85.     /* This is kept around for the sake of error reporting. */
  86.     initrandstate = randstate;
  87. }
  88.  
  89. /* Numbers lifted from Numerical Recipes, p. 198. */
  90. /* Arithmetic must be 32-bit. */
  91.  
  92. int
  93. xrandom(m)
  94. int m;
  95. {
  96.     randstate = (8121 * randstate + 28411) % 134456L;
  97.     return ((m * randstate) / 134456L);
  98. }
  99.  
  100. /* Percentage probability, with bounds checking. */
  101.  
  102. int
  103. probability(prob)
  104. int prob;
  105. {
  106.     if (prob <= 0)
  107.       return FALSE;
  108.     if (prob >= 100)
  109.       return TRUE;
  110.     return (xrandom(100) < prob);
  111. }
  112.  
  113. int
  114. roll_dice(n)
  115. int n;
  116. {
  117.     int numdice, dice, i, rslt;
  118.  
  119.     if (n >> 14 == 0 || n >> 14 == 3)
  120.       return n;
  121.     numdice = (n >> 11) & 0x07;
  122.     dice = (n >> 7) & 0x0f;
  123.     rslt = n & 0x7f;
  124.     for (i = 0; i < numdice; ++i) {
  125.     rslt += xrandom(dice);
  126.     }
  127.     return rslt;
  128. }
  129.  
  130. int
  131. multiply_dice(n, mult)
  132. int n, mult;
  133. {
  134.     int numdice, dice, addend;
  135.  
  136.     if (n >> 14 == 0 || n >> 14 == 3)
  137.       return (n * mult) / 100;
  138.     numdice = (n >> 11) & 0x07;
  139.     dice = (n >> 7) & 0x0f;
  140.     dice = (dice * mult) / 100;
  141.     addend = ((n & 0x7f) * mult) / 100;
  142.     return (1 << 14) | (numdice << 11) | (dice << 7) | (addend & 0x7f);
  143. }
  144.  
  145. /* For a number in the range 0 - 10000, divide it by 100 and use the
  146.    remainder as the probability of adding 1. */
  147.  
  148. int
  149. prob_fraction(n)
  150. int n;
  151. {
  152.   return (n / 100 + (probability(n % 100) ? 1 : 0));
  153. }
  154.  
  155. #ifdef DEBUGGING
  156.  
  157. /* This tracks our total space allocation. */
  158.  
  159. #define NUMMALLOCRECS 200
  160.  
  161. int overflow;
  162.  
  163. int numoverflow;
  164.  
  165. int totmalloc;
  166.  
  167. int nextmalloc;
  168.  
  169. int copymalloc;
  170.  
  171. int grandtotmalloc;
  172.  
  173. struct a_malloc {
  174.     int size;
  175.     int count;
  176. } *mallocs = NULL;
  177.  
  178. static void record_malloc PARAMS ((int amt));
  179. static int malloc_record_compare PARAMS ((const void *m1, const void *m2));
  180.  
  181. /* Given an amount of memory allocated, record it with the others. */
  182.  
  183. static void
  184. record_malloc(amt)
  185. int amt;
  186. {
  187.     int i;
  188.  
  189.     /* Might need to allocate the record of allocations. */
  190.     if (mallocs == NULL) {
  191.     /* Don't use xmalloc here!! */
  192.     mallocs = (struct a_malloc *)
  193.       malloc(NUMMALLOCRECS * sizeof(struct a_malloc));
  194.     overflow = 0;
  195.     numoverflow = 0;
  196.     }
  197.     /* Search for already-recorded allocations of same-size blocks. */
  198.     for (i = 0; i < nextmalloc; ++i) {
  199.     if (amt == mallocs[i].size) {
  200.         ++(mallocs[i].count);
  201.         return;
  202.     }
  203.     }
  204.     if (nextmalloc < NUMMALLOCRECS) {
  205.     /* Record this allocation as a new size of allocation. */
  206.     mallocs[nextmalloc].size = amt;
  207.     mallocs[nextmalloc].count = 1;
  208.     ++nextmalloc;
  209.     } else {
  210.         /* Add to the overflow bucket, which is used for allocations whose
  211.        sizes could not be recorded individually.  Yes, we could allocate
  212.        more buckets, but this seems like too much trouble for an
  213.        uncommon case. */
  214.         overflow += amt;
  215.         ++numoverflow;
  216.     }
  217. }
  218.  
  219. static int
  220. malloc_record_compare(m1, m2)
  221. CONST void *m1, *m2;
  222. {
  223.     return (((struct a_malloc *) m1)->size * ((struct a_malloc *) m1)->count
  224.             - ((struct a_malloc *) m2)->size * ((struct a_malloc *) m2)->count);
  225. }
  226.  
  227. /* Display memory consumption and reset records.  This does not account
  228.    for freeing, but Xconq usually tries to hang onto and reuse anything
  229.    it allocates, very rarely calls free(). */
  230.  
  231. void
  232. report_malloc()
  233. {
  234.     extern int lispmalloc, numsymbols;
  235.     int i;
  236.  
  237.     /* If this is called too soon, just leave silently. */
  238.     if (mallocs == NULL)
  239.       return;
  240.     if (nextmalloc == 0) {
  241.     Dprintf("No mallocs since last report.\n");
  242.     return;
  243.     }
  244.     Dprintf("Mallocs since last report:\n");
  245.     Dprintf("    Amount =  Bytes x  Times\n");
  246.     /* Sort the entries. */
  247.     qsort(mallocs, nextmalloc, sizeof(struct a_malloc), malloc_record_compare);
  248.     /* Write out all the records, formatting nicely. */
  249.     for (i = 0; i < nextmalloc; ++i) {
  250.     Dprintf("%10d = %6d x %6d\n",
  251.         mallocs[i].size * mallocs[i].count,
  252.         mallocs[i].size,  mallocs[i].count);
  253.     }
  254.     if (overflow > 0)
  255.       Dprintf("%10d = ?????? x %6d\n", overflow, numoverflow);
  256.     Dprintf("Total malloced = %d bytes.\n", totmalloc);
  257.     Dprintf("String copies = %d bytes.\n", copymalloc);
  258.     Dprintf("Lisp malloced = %d bytes.\n", lispmalloc);
  259.     Dprintf("Symbols interned = %d.\n", numsymbols);
  260.     Dprintf("Grand total allocation = %d bytes.\n", grandtotmalloc);
  261.     /* Reset all the counters for next time. */
  262.     nextmalloc = 0;
  263.     overflow = numoverflow = 0;
  264.     totmalloc = copymalloc = lispmalloc = 0;
  265. }
  266.  
  267. #endif /* DEBUGGING */
  268.  
  269. /* This is our improved and adapted version of malloc, that guarantees
  270.    zeroing of the block, checks for memory exhaustion, and collects
  271.    usage statistics. */
  272.  
  273. char *
  274. xmalloc(amt)
  275. int amt;
  276. {
  277.     char *value;
  278.  
  279.     if (xmalloc_warnings) {
  280.     run_warning("Should not be calling xmalloc (requested %d bytes)", amt);
  281.     /* Keep going though. */
  282.     }
  283.     if (memory_exhausted)
  284.       return NULL;
  285.     /* Do the actual allocation. */
  286.     value = (char *) malloc(amt);
  287.     if (value == NULL) {
  288. #ifdef DEBUGGING
  289.     if (Debug) {
  290.         Dprintf("Unable to allocate %d bytes.\n", amt);
  291.         /* Write out the allocation report if possible. */
  292.         report_malloc();
  293.     }
  294. #endif /* DEBUGGING */
  295.     /* This is pretty serious, no way to recover. */
  296.     memory_exhausted = TRUE;
  297.     run_error("Memory exhausted!!");
  298.     /* In case run_error doesn't exit. */
  299.       exit(1);
  300.     }
  301.     /* Save callers from having to clear things themselves. */
  302.     memset(value, 0, amt);
  303. #ifdef DEBUGGING
  304.     /* This can't be controlled by `Debug', because much allocation
  305.        happens before any command line or dialog options are interpreted. */
  306.     totmalloc += amt;
  307.     grandtotmalloc += amt;
  308.     record_malloc(amt);
  309. #endif /* DEBUGGING */
  310.     return value;
  311. }
  312.  
  313. /* Like sprintf, but appends. */
  314.  
  315. #ifdef __STDC__
  316. void
  317. tprintf(char *buf, char *str, ...)
  318. {
  319.     va_list ap;
  320.     char line[300];
  321.  
  322.     va_start(ap, str);
  323.     vsprintf(line, str, ap);
  324.     strcat(buf, line);
  325.     va_end(ap);
  326. }
  327.  
  328. void
  329. tnprintf(char *buf, int n, char *str, ...)
  330. {
  331.     va_list ap;
  332.     int n1 = n - strlen(buf);
  333.     char line[300];
  334.  
  335.     if (n1 > 0) {
  336.     va_start(ap, str);
  337.     vsprintf(line, str, ap);
  338.     strncat(buf, line, n1);
  339.     va_end(ap);
  340.     }
  341. }
  342.  
  343. void
  344. vtprintf(char *buf, char *str, va_list ap)
  345. {
  346.     char line[300];
  347.  
  348.     vsprintf(line, str, ap);
  349.     strcat(buf, line);
  350. }
  351. #else
  352. void
  353. tprintf(buf, str, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  354. char *buf, *str;
  355. long a1, a2, a3, a4, a5, a6, a7, a8, a9;
  356. {
  357.     char line[300];
  358.  
  359.     sprintf(line, str, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  360.     strcat(buf, line);
  361. }
  362.  
  363. void
  364. tnprintf(buf, n, str, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  365. char *buf, *str;
  366. int n;
  367. long a1, a2, a3, a4, a5, a6, a7, a8, a9;
  368. {
  369.     int n1 = n - strlen(buf);
  370.     char line[300];
  371.  
  372.     if (n1 > 0) {
  373.     sprintf(line, str, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  374.     strncat(buf, line, n1);
  375.     }
  376. }
  377. #endif
  378.  
  379. /* Copy a string to newly-allocated space.  The new space is never freed. */
  380.  
  381. char *
  382. copy_string(str)
  383. char *str;
  384. {
  385.     int len = strlen(str);
  386.     char *rslt;
  387.  
  388.     rslt = xmalloc(len + 1);
  389.     strcpy(rslt, str);
  390. #ifdef DEBUGGING
  391.     copymalloc += len + 1;
  392. #endif
  393.     return rslt;
  394. }
  395.  
  396. /* Insert the given number of blanks between each char of the string. */
  397.  
  398. char *
  399. pad_blanks(str, n)
  400. char *str;
  401. int n;
  402. {
  403.     char *pb;
  404.     int i;
  405.   
  406.     if (padbuf == NULL)
  407.       padbuf = xmalloc(BUFSIZE);
  408.     pb = padbuf;
  409.     while (*str && pb < padbuf + BUFSIZE - 2) {
  410.     *pb++ = *str++;
  411.     if (*str) {
  412.         for (i = 0; i < n; i++)
  413.           *pb++ = ' ';
  414.     }
  415.     }
  416.     *pb = '\0';
  417.     return padbuf;
  418. }
  419.  
  420. /* Get a *numeric* index into a string (more useful than ptr, in Xconq).
  421.    Return -1 on failed search. */
  422.  
  423. int
  424. iindex(ch, str)
  425. int ch;
  426. char *str;
  427. {
  428.     int i;
  429.  
  430.     if (str == NULL)
  431.       return (-1);
  432.     for (i = 0; str[i] != '\0'; ++i)
  433.       if (ch == str[i])
  434.         return i;
  435.     return (-1);
  436. }
  437.  
  438. /* Return a time difference as an long integer number of seconds. */
  439.  
  440. long
  441. idifftime(t1, t0)
  442. time_t t1, t0;
  443. {
  444. #ifdef MAC /* (should be anywhere that actually has a difftime function) */
  445.     return ((long) difftime(t1, t0));
  446. #else
  447.     return ((long) t1 - (long) t0);
  448. #endif
  449. }
  450.  
  451. /* This little routine goes at the end of all switch statements on internal
  452.    data values. */
  453.  
  454. void
  455. case_panic(str, var)
  456. char *str;
  457. int var;
  458. {
  459.     run_error("Panic! Unknown %s %d", str, var);
  460. }
  461.  
  462. /* Integer square root - good enough, no float trickery or libs needed. */
  463.  
  464. /* Improved version from Bruce Fast, via Scott Herod. */
  465.  
  466. int
  467. isqrt(i)
  468. int i;
  469. {
  470.     int j, k;
  471.  
  472.     if (i > 3) {
  473.         for (j = i, k = -1; j >>= 2; k <<= 1);
  474.         k = (~k + i / ~k) / 2;
  475.     k = (k + i / k) / 2;
  476.     k = (1 + k + i / k) / 2;
  477.     return (k + i / k) / 2;
  478.     } else if (i > 0) {
  479.     return 1;
  480.     } else {
  481.     return 0;
  482.     }
  483. }
  484.  
  485. #ifdef DEBUGGING
  486.  
  487. /* Debugging flags.
  488.    These are set up so that they can be macros or variables, as desired. */
  489.  
  490. #ifndef Debug
  491. int Debug = FALSE;
  492. #endif
  493. #ifndef DebugM
  494. int DebugM = FALSE;
  495. #endif
  496. #ifndef DebugG
  497. int DebugG = FALSE;
  498. #endif
  499.  
  500. /* These are where normal debugging output goes. */
  501.  
  502. FILE *dfp = NULL;
  503. FILE *dgfp = NULL;
  504. FILE *dmfp = NULL;
  505.  
  506. /* Map all the debugging outputs to stdout. */
  507. /* You might think stderr would be a better choice, but this way
  508.    the debugging output is sync'ed properly (read: consistently!)
  509.    with "normal" stdout output. */
  510.  
  511. void
  512. init_debug_to_stdout()
  513. {
  514.        dfp  = stdout;
  515.     dgfp = stdout;
  516.     dmfp = stdout;
  517. }
  518.  
  519. /* Junk associated with debug output. */
  520.  
  521. /* This is all fairly elaborate because we need to be able to collect
  522.    detailed logs of AI activity over different periods of time, and just
  523.    dumping to stdout doesn't work in a window system. */
  524.  
  525. FILE *ffp = NULL;
  526.  
  527. int firstdebug = TRUE;
  528.  
  529. void
  530. update_debugging()
  531. {
  532.     if (Debug || DebugG || DebugM) {
  533.         /* Always close the file if open, forces to desirable state. */
  534.         if (ffp != NULL) {
  535.             fclose(ffp);
  536.             ffp = NULL;
  537.         }
  538.         /* Reopen the file. */
  539.         if (ffp == NULL) {
  540.             ffp = fopen("Xconq.DebugOut", "a");
  541.         }
  542.         if (ffp != NULL) {
  543.             if (Debug)
  544.               dfp = ffp;
  545.             if (DebugG)
  546.               dgfp = ffp;
  547.             if (DebugM)
  548.               dmfp = ffp;
  549.         }
  550.     }
  551. }
  552.  
  553. /* Debug output goes to a file. */
  554.  
  555. void
  556. toggle_debugging(flagp)
  557. int *flagp;
  558. {
  559.     /* Always close the file if open, forces to desirable state. */
  560.     if (ffp != NULL) {
  561.         fclose(ffp);
  562.         ffp = NULL;
  563.     }
  564.     /* Flip the state of the debugging flag, if supplied. */ 
  565.     if (flagp != NULL) {
  566.         *flagp = ! *flagp;
  567.     }
  568.     /* (Re-)open the debugging transcript file. */
  569.     if (ffp == NULL) {
  570.         ffp = fopen("Xconq.DebugOut", (firstdebug ? "w" : "a"));
  571.         firstdebug = FALSE;
  572.     }
  573.     if (ffp != NULL && flagp != NULL) {
  574.         /* Indicate which flags are now on. */
  575.         fprintf(ffp, "\n\n*********** %s %s %s **********\n\n",
  576.                 (Debug ? "Debug" : ""), (DebugM ? "DebugM" : ""),
  577.                 (DebugG ? "DebugG" : ""));
  578.     }
  579.     /* Set specific debug file pointers to be the same as the
  580.        pointer to the file. */
  581.     if (ffp != NULL) {
  582.         if (Debug)
  583.           dfp = ffp;
  584.         if (DebugG)
  585.           dgfp = ffp;
  586.         if (DebugM)
  587.           dmfp = ffp;
  588.     }
  589.     /* If all debugging flags have been turned off, close the file too. */
  590.     if (!Debug && !DebugG && !DebugM) {
  591.         if (ffp != NULL) {
  592.             fclose(ffp);
  593.             ffp = NULL;
  594.         }
  595.     }
  596.     prealloc_debug();
  597. }
  598.  
  599. #ifdef __STDC__
  600.  
  601. void
  602. debug_printf(char *str, ...)
  603. {
  604.     va_list ap;
  605.  
  606.     va_start(ap, str);
  607.     vfprintf(dfp, str, ap);
  608.     va_end(ap);
  609. }
  610.  
  611. void
  612. debugm_printf(char *str, ...)
  613. {
  614.     va_list ap;
  615.  
  616.     va_start(ap, str);
  617.     vfprintf(dmfp, str, ap);
  618.     va_end(ap);
  619. }
  620.  
  621. void
  622. debugg_printf(char *str, ...)
  623. {
  624.     va_list ap;
  625.  
  626.     va_start(ap, str);
  627.     vfprintf(dgfp, str, ap);
  628.     va_end(ap);
  629. }
  630. #else
  631. /* Kind of cheesy, should only use if real ANSI not available. */
  632.  
  633. void
  634. debug_printf(str, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)
  635. char *str;
  636. long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12;
  637. {
  638.     fprintf(dfp, str, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12);
  639. }
  640.  
  641. void
  642. debugm_printf(str, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)
  643. char *str;
  644. long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12;
  645. {
  646.     fprintf(dmfp, str, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12);
  647. }
  648.  
  649. void
  650. debugg_printf(str, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)
  651. char *str;
  652. long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12;
  653. {
  654.     fprintf(dgfp, str, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12);
  655. }
  656. #endif /* __STDC__ */
  657.  
  658. #endif /* DEBUGGING */
  659.  
  660. void
  661. #ifdef __STDC__
  662. init_error(char *str, ...)
  663. #else
  664. init_error(str, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  665. char *str;
  666. long a1, a2, a3, a4, a5, a6, a7, a8, a9;
  667. #endif
  668. {
  669.     char buf[BUFSIZE];
  670.  
  671. #ifdef __STDC__
  672.     {
  673.     va_list ap;
  674.  
  675.     va_start(ap, str);
  676.     vsprintf(buf, str, ap);
  677.     va_end(ap);
  678.     }
  679. #else
  680.     sprintf(buf, str, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  681. #endif
  682.     low_init_error(buf);
  683. }
  684.  
  685. void
  686. #ifdef __STDC__
  687. init_warning(char *str, ...)
  688. #else
  689. init_warning(str, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  690. char *str;
  691. long a1, a2, a3, a4, a5, a6, a7, a8, a9;
  692. #endif
  693. {
  694.     char buf[BUFSIZE];
  695.  
  696.     if (warnings_suppressed)
  697.       return;
  698. #ifdef __STDC__
  699.     {
  700.     va_list ap;
  701.  
  702.     va_start(ap, str);
  703.     vsprintf(buf, str, ap);
  704.     va_end(ap);
  705.     }
  706. #else
  707.     sprintf(buf, str, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  708. #endif
  709.     low_init_warning(buf);
  710. }
  711.  
  712. /* A run error is fatal. */
  713.  
  714. void
  715. #ifdef __STDC__
  716. run_error(char *str, ...)
  717. #else
  718. run_error(str, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  719. char *str;
  720. long a1, a2, a3, a4, a5, a6, a7, a8, a9;
  721. #endif
  722. {
  723.     char buf[BUFSIZE];
  724.  
  725. #ifdef __STDC__
  726.     {
  727.     va_list ap;
  728.  
  729.     va_start(ap, str);
  730.     vsprintf(buf, str, ap);
  731.     va_end(ap);
  732.     }
  733. #else
  734.     sprintf(buf, str, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  735. #endif
  736.     low_run_error(buf);
  737. }
  738.  
  739. /* Runtime warnings are for when it's important to bug the players,
  740.    usually a problem with Xconq or a game design. */
  741.  
  742. void
  743. #ifdef __STDC__
  744. run_warning(char *str, ...)
  745. #else
  746. run_warning(str, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  747. char *str;
  748. long a1, a2, a3, a4, a5, a6, a7, a8, a9;
  749. #endif
  750. {
  751.     char buf[BUFSIZE];
  752.  
  753.     if (warnings_suppressed)
  754.       return;
  755. #ifdef __STDC__
  756.     {
  757.     va_list ap;
  758.  
  759.     va_start(ap, str);
  760.     vsprintf(buf, str, ap);
  761.     va_end(ap);
  762.     }
  763. #else
  764.     sprintf(buf, str, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  765. #endif
  766.     low_run_warning(buf);
  767. }
  768.